const fs = require('fs');
const path = require('path');

const IGNORED_FILES = new Set(["index.md", "assets"]); // 忽略的文件
const sortWeight = {
    "其他": 10,  
    "其它": 10,
};


const weightSort = (list) => {
    // 将dirList分为两部分：存在于sortWeight中的元素和其他元素
    const weightedItems = [];
    const otherItems = [];

    list.forEach(item => {
        let sortBy = typeof item === 'string' ? item : item.text
        if (sortWeight.hasOwnProperty(sortBy)) {
            weightedItems.push(item);
        } else {
            otherItems.push(item);
        }
    });

    // 首先对所有元素按字母顺序排序
    otherItems.sort();
    weightedItems.sort((a, b) => {
        return sortWeight[a.text] - sortWeight[b.text];
    });

    // 返回合并后的结果：先是按字母排序的其他元素，再是按权重排序的元素
    return [...otherItems, ...weightedItems];
}

export class postsTools {
    constructor(vitepressDir) {
        this.configDir = path.join(vitepressDir, '.vitepress');
        this.postDir = path.join(vitepressDir, 'posts');
    }

    #generateNavConfig() {
        const buildItems = (entry) => {
            const subDir = path.join(this.postDir, entry);
            const items = fs.readdirSync(subDir)
                .filter((subEntry) => !IGNORED_FILES.has(subEntry))
                .map((subEntry) => ({
                    text: subEntry,
                    link: `/posts/${entry}/${subEntry}/`
                }));
            return weightSort(items);
        };

        const navItems = [{ text: 'Home', link: '/' }];

        fs.readdirSync(this.postDir).forEach((entry) => {
            const entryPath = path.join(this.postDir, entry);
            if (fs.statSync(entryPath).isDirectory()) {
                navItems.push({
                    text: entry,
                    items: buildItems(entry)
                });
            }
        });
        return weightSort(navItems);
    }

    #generateSidebarConfig() {
        const buildItems = (relPath) => {
            const absPath = path.join(this.postDir, relPath);
            const dirItems = [];
            const fileItems = [];

            const entries = fs.readdirSync(absPath).filter(entry => !IGNORED_FILES.has(entry));
            entries.forEach((entry) => {
                const entryPath = path.join(relPath, entry);
                const fullPath = path.join(absPath, entry);
                const stats = fs.statSync(fullPath);
                
                if (stats.isDirectory()){
                    dirItems.push({
                        text: entry[0].toUpperCase() + entry.slice(1),
                        type: 'directory',
                        collapsed: true,
                        items: buildItems(entryPath)
                    })
                }else if (stats.isFile()){
                    fileItems.push({
                        text: entry.replace('.md', '').replace(/^\w/, (c) => c.toUpperCase()),
                        type: 'file',
                        link: `/posts/${entryPath}`
                    })
                }
            })
            return [...weightSort(dirItems), ...weightSort(fileItems)];
        };

        const sidebarConfig = {};
        fs.readdirSync(this.postDir).forEach((subDir) => {
            const subPath = path.join(this.postDir, subDir);
            if (!fs.statSync(subPath).isDirectory()) return;

            fs.readdirSync(subPath).forEach((subSubDir) => {
                const subSubPath = path.join(subPath, subSubDir);
                if (fs.statSync(subSubPath).isDirectory()) {
                    sidebarConfig[`/posts/${subDir}/${subSubDir}/`] = buildItems(path.join(subDir, subSubDir));
                }
            });
        });

        return sidebarConfig;
    }

    generateConfig() {
        const navConfig = this.#generateNavConfig();
        const sidebarConfig = this.#generateSidebarConfig();

        // Write navConfig.js
        fs.writeFileSync(
            path.join(this.configDir, 'navConfig.js'),
            `export const navConfig = ${JSON.stringify(navConfig, null, 4)};`,
            'utf-8'
        );

        // Write sidebarConfig.js
        fs.writeFileSync(
            path.join(this.configDir, 'sidebarConfig.js'),
            `export const sidebarConfig = ${JSON.stringify(sidebarConfig, null, 4)};`,
            'utf-8'
        );
    };


    getDirectoryTree(dirPath) {
        const directories = [];
        const files = [];

        const items = fs.readdirSync(dirPath);  // 读取目录中的所有文件和文件夹
        const sortedItems = weightSort(items)  // 按照权重排序

        for (const item of sortedItems) {
            if (IGNORED_FILES.has(item)) {
                continue;
            }
            const itemPath = path.join(dirPath, item);
            const stats = fs.statSync(itemPath);
            // 如果是文件夹，递归处理
            if (stats.isDirectory()) {
                directories.push({
                    id: itemPath.split("posts\\")[1].replace(/\\/g, '/'), // 使用文件夹路径作为id
                    label: item, // 使用文件夹名称作为label
                    children: this.getDirectoryTree(itemPath), // 递归获取子目录
                });
            }else{
                // 如果是文件，直接添加label
                files.push({
                    id: itemPath.split("posts\\")[1].replace(/\\/g, '/'),
                    label: item
                });
            }
 
        }
        return [...directories, ...files];
    };

    getMoveTree(dirPath, stoppedID) {
        const directories = [];

        const items = fs.readdirSync(dirPath);  // 读取目录中的所有文件和文件夹
        const sortedItems = weightSort(items)  // 按照权重排序

        for (const item of sortedItems) {
            if (IGNORED_FILES.has(item)) {
                continue;
            }
            const itemPath = path.join(dirPath, item);
            const stats = fs.statSync(itemPath);
            // 如果是文件夹，递归处理
            if (stats.isDirectory()) {
                const id = itemPath.split("posts\\")[1].replace(/\\/g, '/')
                if (id === stoppedID) {
                    continue;
                }
                directories.push({
                    id: id, // 使用文件夹路径作为id
                    label: item, // 使用文件夹名称作为label
                    children: this.getMoveTree(itemPath, stoppedID), // 递归获取子目录
                });
            }
        }
        return [...directories];
    }
}


